package itsm.isperp.module.service.project;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import itsm.isperp.control.form.table.TreeTable;
import itsm.isperp.framework.collection.tree.ITreeNode;
import itsm.isperp.framework.core.context.ContextHolder;
import itsm.isperp.framework.data.domain.DataRequest;
import itsm.isperp.framework.service.TreeNodeService;
import itsm.isperp.framework.utils.TreeNodeUtils;
import itsm.isperp.framework.web.request.JqGridFilterRuleOp;
import itsm.isperp.framework.web.request.JqGridRequest;
import itsm.isperp.module.dto.project.ProjCostTemplateDTO;
import itsm.isperp.module.entity.project.ProjCostItem;
import itsm.isperp.module.entity.project.ProjCostTemplate;
import itsm.isperp.module.repository.project.ProjCostTemplateMapper;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

/**
 * 项目预算管理服务类
 * 
 * @author lizx
 * @date 2013-3-2
 * @version V1.0
 * 
 */
@Service
public class ProjCostTemplateService extends TreeNodeService<ProjCostTemplate> {

	@Autowired
	protected ProjCostTemplateMapper projCostTemplateMapper;

	@Override
	public ProjCostTemplateMapper getRepository() {
		return this.projCostTemplateMapper;
	}

	/**
	 * 获取项目模板列表
	 * 
	 * @return
	 */
	public List<ProjCostTemplate> findTemplates() {
		JqGridRequest req = new JqGridRequest();
		req.isPageable(false);
		req.setSearchString("parent_id ='' Or parent_id IS NULL");
		return getRepository().findAllByRequest(req).getContent();
	}

	@Override
	public List<ProjCostTemplate> getTree(String parentId) {
		DataRequest request = new JqGridRequest()
				.setSelectColumns("id",
						"CONCAT(CONCAT(CONCAT('(',code),')'),name) AS name",
						"parent_id", "treenode_path", "treenode_name_path",
						"open").isPageable(false)
				.setSort("order_num", Direction.ASC);

		if (StringUtils.isNotEmpty(parentId)) {

			ProjCostTemplate p = this.findOne(parentId);
			request.addFilterRule("treenode_path", JqGridFilterRuleOp.bw,
					p.getTreenodePath());
		}
		List<ProjCostTemplate> list = this.getRepository()
				.findAllByRequest(request).getContent();

		return TreeNodeUtils.parseAndAddRootFormList(ProjCostTemplate.class,
				list, true);
	}

	/**
	 * 获取预算树形结构
	 * 
	 * @param projectId
	 *            项目id
	 * @param parentId
	 *            父级模板id
	 * @return 预算树形结构
	 */
	@Deprecated
	public List<ProjCostTemplateDTO> getCostTree(String projectId,
			String parentId) {
		DataRequest request = new JqGridRequest()
				.setSelectColumns("id", "code",
						"CONCAT(CONCAT(code,':'),name) AS name", "fix_amount",
						"calculate_formula", "parent_id", "treenode_path",
						"treenode_name_path", "open").isPageable(false)
				.setSort("order_num", Direction.ASC);

		if (StringUtils.isNotEmpty(parentId)) {

			ProjCostTemplate p = this.findOne(parentId);
			request.addFilterRule("treenode_path", JqGridFilterRuleOp.bw,
					p.getTreenodePath());
		}

		// 脚本变量
		Map<String, Object> vars = new HashMap<String, Object>();
		Binding bd = new Binding(vars);
		GroovyShell shell = new GroovyShell(bd);
		// 计算脚本
		StringBuilder script = new StringBuilder();

		ProjProjectService projProjectService = ContextHolder
				.getSpringBean("projProjectService");

		ProjCostItemService projCostItemService = ContextHolder
				.getSpringBean("projCostItemService");

		int account = projProjectService.getProjectAccount(projectId);

		List<ProjCostTemplate> list = this.getRepository()
				.findAllByRequest(request).getContent();

		List<ProjCostTemplateDTO> nodes = new ArrayList<>();

		List<ProjCostItem> items = projCostItemService.getProjectCost(
				projectId, parentId);

		for (ProjCostTemplate n : list) {
			// 获取模板定义
			if (n.isFixAmount()
					&& StringUtils.isNotBlank(n.getCalculateFormula())) {

				vars.put(n.getCode(), "");
				script.append(n.getCode()).append("=")
						.append(n.getCalculateFormula()).append(";");

				ProjCostTemplateDTO tn = new ProjCostTemplateDTO(n);

				tn.setName(n.getName() + "=" + n.getCalculateFormula());
				nodes.add(tn);
			} else {
				addToList(items, n, nodes);
			}
		}

		// 用于显示的格式化树形列表
		List<ProjCostTemplateDTO> result = TreeNodeUtils.parseFormList(nodes);

		// 加入所有项目的计算公式
		vars.put(result.get(0).getCode(), account);

		shell.evaluate(script.toString().replace("%", "/100"));

		// 取计算结果
		for (ProjCostTemplateDTO n : nodes) {
			// 判断是否为固定预算
			if (n.isFixAmount()
					&& StringUtils.isNotBlank(n.getCalculateFormula())) {
				n.setAmount((int) Float.parseFloat(shell.getVariable(
						n.getCode()).toString()));
			}
		}

		// 设置顶级节点名称
		result.get(0).setName(result.get(0).getName() + " =" + account);
		return result;
	}

	/**
	 * 
	 * @param projectId
	 * @return
	 */
	public List<Map<String, Object>> findAcccountingItemByProject(
			String projectId) {
		ProjProjectService projProjectService = ContextHolder
				.getSpringBean("projProjectService");
		Map<String, Object> map = projProjectService.findOneToMap(projectId,
				"proj_cost_template_id");

		if (MapUtils.isEmpty(map)) {
			return null;
		}
		String tempId = map.get("proj_cost_template_id").toString();

		return this.getRepository().getCostSubjectItem("/" + tempId + "/%");

	}

	/**
	 * 转换并添加到预算预算模板节点DTO列表中
	 * 
	 * @param items
	 *            预算项列表
	 * @param n
	 *            预算模板节点
	 * @param nodes
	 *            预算模板节点DTO列表
	 */
	private void addToList(final List<ProjCostItem> items,
			final ProjCostTemplate n, List<ProjCostTemplateDTO> nodes) {
		boolean flag = true;

		for (ProjCostItem item : items) {
			if (n.getId().equals(item.getProjCostTemplateNodeId())) {
				ProjCostTemplateDTO tn = new ProjCostTemplateDTO(n);
				tn.setAmount(item.getAmount());
				nodes.add(tn);
				flag = false;
				break;
			}
		}

		if (flag) {
			nodes.add(new ProjCostTemplateDTO(n));
		}
	}

	public boolean templateUseInProject(String id) {

		JdbcTemplate jdbcTemplate = ContextHolder
				.getSpringBean(JdbcTemplate.class);

		Map<String, Object> result = jdbcTemplate
				.queryForMap(
						"SELECT count(1) count_t FROM proj_project WHERE proj_cost_template_id=?",
						id);
		if (result != null && result.size() == 1) {
			int count_t = Integer.parseInt(result.get("count_t").toString());
			if (count_t > 0) {
				return true;
			}
		}
		return false;
	}

	public TreeTable getCostTreeTable(String projCostTemplateId) {
		List<Map<String, Object>> costs = this.getRepository().getCost(
				"/" + projCostTemplateId + "/%");

		costs = TreeNodeUtils.sortTree(costs);

		TreeTable tt = new TreeTable();
		for (Map<String, Object> m : costs) {
			long count_id = Long.valueOf(m.get("count_id").toString());
			if (count_id == 1) {
				String id = (String) m.get("id");
				String treenodeName = (String) m.get("treenode_name_path");
				String code = (String) m.get("code");
				String cal = (String) m.get("calculate_formula");
				Object objValue = m.get("amount");
				String value = "";
				if (objValue != null) {
					value = objValue.toString();
				}

				tt.addRow(id, treenodeName, code, cal, value);
			}
		}

		return tt;
	}
}
